package wassalt.client;

import static wassalt.Utils.AppConstants.END_DATE_PARAM;
import static wassalt.Utils.AppConstants.ID_OWNER_PARAM;
import static wassalt.Utils.AppConstants.NTYPE_PARAM;
import static wassalt.Utils.AppConstants.PLACE_PARAM;
import static wassalt.Utils.AppConstants.START_DATE_PARAM;
import static wassalt.Utils.AppConstants.TYPE_PARAM;
import static wassalt.Utils.AppConstants.WHEN_PARAM;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.regex.Pattern;

import org.json.JSONArray;
import org.json.JSONObject;

import wassalt.Utils.AppConstants;
import wassalt.Utils.DbAdapter;
import wassalt.Utils.User;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.location.Address;
import android.location.Geocoder;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.MultiAutoCompleteTextView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

import com.google.android.maps.GeoPoint;

/**
 * @author Dalia
 * @author Iman
 * @author loai
 * 
 *         Superclass for all Notifications (create or request)
 * */

public class CreateNotification extends Activity {

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		// case R.id.addFavoritNotifmenuButton:
		// break;
		case R.id.FavoritNotifmenuButton:
			startActivity(new Intent(this, FavoriteNotificationsActivity.class));
			finish();
			break;
		}
		return true;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.create_notification_menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	// debugging tag
	protected String TAG = "CreateNotification";

	// helper activities codes
	private static final int PICK_CONTACT = 1;
	private static final int PICK_CONTACT_2 = 3;
	private static final int PICK_DESTINATION = 2;

	// unique identifiers for the date and time dialogs
	static final int DATE_DIALOG_start = 0;
	static final int DATE_DIALOG_end = 1;
	static final int TIME_DIALOG_start = 2;
	static final int TIME_DIALOG_end = 3;

	// to store the phone numbers of a contact
	LinkedList<String> phoneList;

	// database path
	protected String path;

	// database columns
	long currentUserId;
	String user_phone;
	String phoneReceivers = ""; // contact phone number
	String place = "";// "30.058056,31.228889"; //in the form
						// (latitude,longitude)
	boolean type = false; // 1 for distance, 0 for time
	int when = 5; // number in minutes or meters

	String names = "";

	private TextView startDate;
	private TextView endDate;
	private TextView startTime;
	private TextView endTime;

	private ImageView startPickDate;
	private ImageView endPickDate;
	private ImageView startPickTime;
	private ImageView endPickTime;

	// date and time
	private int Year = 2012;
	private int Month = 1;
	private int Day = 1;
	private int Hour = 1;
	private int Minute = 1;

	protected NotificationAdapter adapter = null;
	LinearLayout notificationsList = null;
	JSONArray phoneReceiversJson = new JSONArray();

	Calendar start;
	Calendar end;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.notification_form);
		Bundle bundle = getIntent().getExtras();

		notificationsList = (LinearLayout) findViewById(R.id.notifications_linear);
		// notificationsList.setSh
		Log.e("Initial capacity", notificationsList.getChildCount() + "");
		adapter = new NotificationAdapter(notificationsList);
		User currentUser = User.loadUser(this);
		currentUserId = currentUser.getId();
		user_phone = currentUser.getPhone();

		start = Calendar.getInstance();
		end = Calendar.getInstance();
		end.set(Calendar.YEAR, 2099);
		startPickDate = (ImageView) findViewById(R.id.calenderButtonStart);
		startPickDate.setTag(R.integer.DIALOG_TAG, DATE_DIALOG_start);

		endPickDate = (ImageView) findViewById(R.id.calenderButtonEnd);
		endPickDate.setTag(R.integer.DIALOG_TAG, DATE_DIALOG_end);

		startPickTime = (ImageView) findViewById(R.id.TimeButtonStart);
		startPickTime.setTag(R.integer.DIALOG_TAG, TIME_DIALOG_start);

		endPickTime = (ImageView) findViewById(R.id.TimeButtonEnd);
		endPickTime.setTag(R.integer.DIALOG_TAG, TIME_DIALOG_end);
		startDate = (TextView) findViewById(R.id.startDate);
		endDate = (TextView) findViewById(R.id.endDate);
		startTime = (TextView) findViewById(R.id.startTime);
		endTime = (TextView) findViewById(R.id.endTime);

		startPickDate.setOnClickListener(dateImageClickListener);
		endPickDate.setOnClickListener(dateImageClickListener);
		startPickTime.setOnClickListener(dateImageClickListener);
		endPickTime.setOnClickListener(dateImageClickListener);
		refreshDates();

		MultiAutoCompleteTextView contact = (MultiAutoCompleteTextView) findViewById(R.id.AddContact);

		ContentResolver content = getContentResolver();
		Cursor cursor = content.query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
				PEOPLE_PROJECTION, null, null, null);
		ContactsAdapter adapter = new ContactsAdapter(this, cursor);
		contact.setThreshold(0);
		contact.setAdapter(adapter);
		contact.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());

		if (bundle != null) {
			// i.e. loads from favorite
			View v = notificationsList.getChildAt(0);
			if (!(this instanceof CreateAlarm)) {
				String names = bundle.getString(AppConstants.CNAME);
				String phoneReceivers = bundle.getString(AppConstants.CPHONE);
				contact.setText(names + " <" + phoneReceivers + ">");
				Log.e("Names", names);
				Log.e("phoneReceivers", phoneReceivers);
			}
			EditText address = (EditText) v.findViewById(R.id.address);
			address.setText(bundle.getString(AppConstants.LOCATION));

			EditText when = (EditText) v.findViewById(R.id.amount);
			when.setText(bundle.getString(AppConstants.VALUE));

			Spinner distanceTime = (Spinner) v.findViewById(R.id.spinner_when);
			boolean type = bundle.getString(AppConstants.TYPE).equals(
					AppConstants.TIME);
			distanceTime.setSelection(type ? 0 : 1);
			this.adapter.get(0).type = type;
		}

	}

	public static final String[] PEOPLE_PROJECTION = new String[] {
			ContactsContract.CommonDataKinds.Phone._ID,
			ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
			ContactsContract.CommonDataKinds.Phone.NUMBER

	};

	/**
	 * Returns the notifications data in jsonArray
	 * 
	 * @author loai
	 */
	public String getData() {
		try {
			JSONArray array = new JSONArray();
			for (int i = 0; i < adapter.size(); i++) {
				JSONObject js = new JSONObject();
				Notification notif = adapter.get(i);
				js.put(ID_OWNER_PARAM, currentUserId);
				js.put(PLACE_PARAM, adapter.getPlace(i));
				js.put(TYPE_PARAM, notif.type);
				js.put(WHEN_PARAM, adapter.getWhen(i));
				js.put(START_DATE_PARAM, start.getTime().toLocaleString());
				js.put(END_DATE_PARAM, end.getTime().toLocaleString());
				if (this instanceof CreateRequest)
					js.put(NTYPE_PARAM, AppConstants.REQUEST);
				else if (this instanceof CreateOffer)
					js.put(NTYPE_PARAM, AppConstants.OFFER);
				else if (this instanceof CreateAlarm)
					js.put(NTYPE_PARAM, AppConstants.ALARM);
				array.put(js);
			}
			return URLEncoder.encode(array.toString());
		} catch (Exception e) {
			Log.e("Exception", e.getMessage());
			return null;
		}
	}

	/**
	 * to fix the representation of the time
	 * 
	 * @author Emy
	 * @param c
	 *            : time
	 * @return a string: the appropriate representation of the time ==> the
	 *         single digit are preceded by a 0
	 */
	private static String pad(int c) {
		if (c >= 10)
			return String.valueOf(c);
		else
			return "0" + String.valueOf(c);
	}

	private OnItemSelectedListener distanceTimeListener = new OnItemSelectedListener() {

		@Override
		public void onItemSelected(AdapterView<?> parent, View view,
				int position, long id) {
			adapter.itemPos = (Integer) parent.getTag(R.integer.INDEX_TAG);
			adapter.getSelected().type = position == 0 ? false : true;
		}

		@Override
		public void onNothingSelected(AdapterView<?> parent) {
			// TODO Auto-generated method stub

		}
	};
	/**
	 * A listener for clicking on date and time images
	 * 
	 * @author loai
	 */
	private OnClickListener dateImageClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			showDialog((Integer) v.getTag(R.integer.DIALOG_TAG));
		}
	};
	/**
	 * A listener for clicking on date and time images
	 * 
	 * @author loai
	 */
	private OnClickListener addRemoveImageClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			// adapter.itemPos = notificationsList.getPositionForView((View) v
			// .getParent());
			adapter.itemPos = (Integer) v.getTag(R.integer.INDEX_TAG);
			if (v.getId() == R.id.addNotificationButton)
				adapter.addNotification(adapter.itemPos + 1);
			else
				adapter.removeNotification(adapter.itemPos);
		}
	};
	private OnClickListener time_distanceClickListener = new OnClickListener() {

		@Override
		public void onClick(View v) {
			CheckBox check = (CheckBox) v;
			if (check.isChecked()) {

			} else {
				start = Calendar.getInstance();
				end = Calendar.getInstance();
				end.set(Calendar.YEAR, 2099);
			}
			refreshDates();
		}
	};

	/**
	 * Refreshs the start and end dates view
	 * 
	 * @author loai
	 */
	public void refreshDates() {

		// capture the View elements concerning the date and time

		startDate.setText(new StringBuilder()
				.append(getString(R.string.startDate) + "\t")
				.append(pad(start.get(Calendar.DATE))).append("-")
				.append(pad(start.get(Calendar.MONTH) + 1)).append("-")
				.append(pad(start.get(Calendar.YEAR))).append(" "));

		endDate.setText(new StringBuilder()
				.append(getString(R.string.endDate) + "  \t")
				.append(pad(end.get(Calendar.DATE))).append("-")
				.append(pad(end.get(Calendar.MONTH) + 1)).append("-")
				.append(pad(end.get(Calendar.YEAR))).append(" "));

		startTime.setText(new StringBuilder()
				.append(pad(start.get(Calendar.HOUR_OF_DAY))).append(":")
				.append(pad(start.get(Calendar.MINUTE))));

		endTime.setText(new StringBuilder()
				.append(pad(end.get(Calendar.HOUR_OF_DAY))).append(":")
				.append(pad(end.get(Calendar.MINUTE))));

		CheckBox time_distance = (CheckBox) findViewById(R.id.optional);
		time_distance.setOnClickListener(time_distanceClickListener);

		int visibility = time_distance.isChecked() ? android.view.View.VISIBLE
				: android.view.View.GONE;
		startDate.setVisibility(visibility);
		endDate.setVisibility(visibility);
		startTime.setVisibility(visibility);
		endTime.setVisibility(visibility);
		startPickDate.setVisibility(visibility);
		endPickDate.setVisibility(visibility);
		startPickTime.setVisibility(visibility);
		endPickTime.setVisibility(visibility);
	}

	/**
	 * @author Emy for picking the start date: When the user is done setting the
	 *         date (clicks the "Set" button), the onDateSet() method is called
	 *         and it updates the member fields with the new date and updates
	 *         the layout's TextView. ==> update the day, month and year
	 */
	private DatePickerDialog.OnDateSetListener startDateSetListener = new DatePickerDialog.OnDateSetListener() {

		public void onDateSet(DatePicker view, int year, int monthOfYear,
				int dayOfMonth) {
			start.set(Calendar.YEAR, year);
			start.set(Calendar.MONTH, monthOfYear);
			start.set(Calendar.DATE, dayOfMonth);
			refreshDates();
		}
	};

	/**
	 * @author Emy for picking the end date: When the user is done setting the
	 *         date (clicks the "Set" button), the onDateSet() method is called
	 *         and it updates the member fields with the new date and updates
	 *         the layout's TextView. ==> update the day, month and year
	 */
	private DatePickerDialog.OnDateSetListener endDateSetListener = new DatePickerDialog.OnDateSetListener() {

		public void onDateSet(DatePicker view, int year, int monthOfYear,
				int dayOfMonth) {
			end.set(Calendar.YEAR, year);
			end.set(Calendar.MONTH, monthOfYear);
			end.set(Calendar.DATE, dayOfMonth);
			refreshDates();
		}
	};

	/**
	 * @author Emy for picking the start time: When the user is done setting the
	 *         time (clicks the "Set" button), the onTimeSet() method is called
	 *         and it updates the member fields with the new date and updates
	 *         the layout's TextView. ==> update the hour and minute
	 */
	private TimePickerDialog.OnTimeSetListener startTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
		public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
			start.set(Calendar.HOUR_OF_DAY, hourOfDay);
			start.set(Calendar.MINUTE, minute);
			refreshDates();
		}
	};

	/**
	 * @author Emy for picking the end time: When the user is done setting the
	 *         time (clicks the "Set" button), the onTimeSet() method is called
	 *         and it updates the member fields with the new date and updates
	 *         the layout's TextView. ==> update the hour and minute
	 */
	private TimePickerDialog.OnTimeSetListener endTimeSetListener = new TimePickerDialog.OnTimeSetListener() {
		public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
			end.set(Calendar.HOUR_OF_DAY, hourOfDay);
			end.set(Calendar.MINUTE, minute);
			refreshDates();
		}
	};

	/**
	 * @author Emy According to the unique id passed that is passed in the
	 *         showDialog(int) method, the DatePickerDialog or the
	 *         TimePickerDialog (depending on the id) is instantiated with the
	 *         corresponding variables
	 */
	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DATE_DIALOG_start:
			return new DatePickerDialog(this, startDateSetListener, Year,
					Month, Day);

		case DATE_DIALOG_end:
			return new DatePickerDialog(this, endDateSetListener, Year, Month,
					Day);
		case TIME_DIALOG_start:
			return new TimePickerDialog(this, startTimeSetListener, Hour,
					Minute, false);
		case TIME_DIALOG_end:
			return new TimePickerDialog(this, endTimeSetListener, Hour, Minute,
					false);

		}
		return null;
	}

	public void openContacts(View view) {
		/*
		 * currently will pick only one contact Intent intent = new
		 * Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
		 * startActivityForResult(intent, PICK_CONTACT);
		 */
		String[] menuItems = getResources().getStringArray(
				R.array.contact_loading_options);

		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getResources().getString(R.string.loading_preference));

		builder.setItems(menuItems, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {

				Intent intent = new Intent();

				switch (item) {
				case 0:
					intent.setClass(getApplicationContext(),
							LoadContactActivity.class);

					break;
				case 1:
					intent.setClass(getApplicationContext(),
							FavoriteClientsActivity.class);
				}
				startActivityForResult(intent, PICK_CONTACT_2);
			}
		});

		AlertDialog alert = builder.create();
		alert.show();
	}

	/**
	 * @author Dalia
	 * 
	 *         Opens the map to let the user selected destination.
	 * **/
	public void openMap(View view) {
		// Mark this as selected
		adapter.itemPos = (Integer) view.getTag(R.integer.INDEX_TAG);
		// open map returning longitude and latitude
		Intent intent = new Intent(this, Map.class);

		startActivityForResult(intent, PICK_DESTINATION);
	}

	/**
	 * @author Dalia : destination
	 * @author Iman : contact
	 * 
	 *         Handles the different results returned by helper activities.
	 * ***/
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case PICK_CONTACT:
			if (resultCode == Activity.RESULT_OK) {
				try {
					TextView error = (TextView) findViewById(R.id.contact_error);
					MultiAutoCompleteTextView contact = (MultiAutoCompleteTextView) findViewById(R.id.AddContact);

					// Get the Uri for the data returned by the contact picker
					// This Uri identifies the person picked
					Uri contactData = data.getData();

					// Query the table
					Cursor contactsCursor = managedQuery(contactData, null,
							null, null, null);

					// If the cursor is not empty
					if (contactsCursor.moveToFirst()) {

						// Get the id name and phone number indicator
						String id = contactsCursor
								.getString(contactsCursor
										.getColumnIndexOrThrow(ContactsContract.Contacts._ID));
						String name = contactsCursor
								.getString(contactsCursor
										.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
						String hasPhoneNumber = contactsCursor
								.getString(contactsCursor
										.getColumnIndexOrThrow(ContactsContract.Contacts.HAS_PHONE_NUMBER));
						// If the contact has a phone number
						if (Integer.parseInt(hasPhoneNumber) > 0) {
							error.setText("");
							phoneList = new LinkedList<String>();
							queryAllPhoneNumbersForContact(
									Integer.parseInt(id), phoneList);
							if (phoneList.size() == 0) {
								phoneReceivers = "";
								contact.setText(phoneReceivers);
								error.setText(R.string.no_mobile_error);
							} else {
								if (phoneList.size() == 1) {
									String phoneNo = phoneList.get(0);
									phoneReceivers = "";
									for (int i = 0; i < phoneNo.length(); i++) {
										if (phoneNo.charAt(i) != '-')
											phoneReceivers = phoneReceivers
													+ phoneNo.charAt(i);

									}
									if (phoneReceivers.length() != 14) {
										phoneReceivers = "002" + phoneReceivers;
									}
									contact.setText(phoneReceivers);
								} else {
									phoneReceivers = "";
									display_popup();
								}
							}
						} else {
							phoneReceivers = "";
							Toast.makeText(this, R.string.phone_error, 0)
									.show();
							contact.setText(phoneReceivers);
							error.setText(R.string.phone_error);
							// user can decide to cancel or choose another
							// contact!
						}
					}
				} catch (Exception e) {
					Log.e(TAG, "Failed!", e);
				}
			}
			break;

		case PICK_CONTACT_2:
			if (resultCode == AppConstants.SUCCESS) {
				Bundle b = data.getExtras();
				processBundle(b);
			}
		case PICK_DESTINATION:
			if (resultCode == Activity.RESULT_OK) {
				double longi = data.getDoubleExtra("longitude", 0);
				double lat = data.getDoubleExtra("latitude", 0);
				String address = data.getStringExtra("address");
				Toast.makeText(getApplicationContext(), longi + " " + lat,
						Toast.LENGTH_SHORT).show();
				adapter.getSelected().setLocation(lat, longi);
				// set place, temp usage only
				if (adapter.itemPos == 0)
					place = adapter.getPlace(0);
				adapter.notifyDataSetChanged();
				// display to the user
				// EditText addr = (EditText) findViewById(R.id.address);
				// addr.setText(place);// (address=="")?place:address);
			}
			break;

		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	/**
	 * Processes the result returning from the contact selection
	 * 
	 * @author Aya Kamel
	 * @param b
	 *            The bundle containing names and corresponding phones. In case
	 *            of multiple phones they are separated by ", " (comma then
	 *            space)
	 */
	private void processBundle(Bundle b) {

		ArrayList<String> names_list = b.getStringArrayList("SelectedNames");
		ArrayList<String> phones = b.getStringArrayList("SelectedPhones");

		MultiAutoCompleteTextView contact = (MultiAutoCompleteTextView) findViewById(R.id.AddContact);
		// String phoneReceivers = formulatePhone(phones.get(0));
		names = names_list.get(0);
		String display_contacts = names_list.get(0) + " <" + phones.get(0)
				+ ">";
		for (int i = 1; i < phones.size(); i++) {
			names += ", " + names_list.get(i);
			// phoneReceivers += "; " + formulatePhone(phones.get(i));
			display_contacts += ", " + names_list.get(i) + " <" + phones.get(i)
					+ ">";
		}
		// contact.setText(phoneReceivers);
		contact.setText(display_contacts);
		CheckBox checkBox = (CheckBox) findViewById(R.id.favortite_contacts);
		checkBox.setEnabled(true);
	}

	/**
	 * Takes as input a phone number and changes the number to suit the form
	 * 002(11-digit-number)
	 * 
	 * @param this_phone
	 * @return
	 */
	private String formulatePhone(String this_phone) {
		this_phone = this_phone.replace("-", "");
		this_phone = this_phone.replace(">", "");
		this_phone = this_phone.replace(" ", "");
		// Apply some type casting on the string
		this_phone = this_phone.replace("+2", "002");

		// to avoid adding 002 to a home number
		if ((this_phone.length() == 10) || (this_phone.length() == 11))
			this_phone = "002".concat(this_phone);
		return this_phone;
	}

	public void queryAllPhoneNumbersForContact(int contactId,
			LinkedList<String> phoneList) {
		final String[] projection = new String[] { Phone.NUMBER, Phone.TYPE, };

		final Cursor phone_cursor = managedQuery(Phone.CONTENT_URI, projection,
				Data.CONTACT_ID + "=?",
				new String[] { String.valueOf(contactId) }, null);

		if (phone_cursor.moveToFirst()) {
			final int contactNumberColumnIndex = phone_cursor
					.getColumnIndex(Phone.NUMBER);
			final int contactTypeColumnIndex = phone_cursor
					.getColumnIndex(Phone.TYPE);

			while (!phone_cursor.isAfterLast()) {
				final String number = phone_cursor
						.getString(contactNumberColumnIndex);
				final int type = phone_cursor.getInt(contactTypeColumnIndex);
				if (type == 2)
					phoneList.add(number);
				phone_cursor.moveToNext();
			}

		}
		phone_cursor.close();
	}

	public void display_popup() {
		AlertDialog.Builder window = new Builder(this);
		final String[] phones = new String[phoneList.size()];

		for (int i = 0; i < phoneList.size(); i++) {
			phones[i] = phoneList.get(i);
		}

		window.setTitle(R.string.window_title);
		window.setItems(phones, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int item) {
				String phoneNo = phones[item];
				for (int i = 0; i < phoneNo.length(); i++) {
					if (phoneNo.charAt(i) != '-')
						phoneReceivers = phoneReceivers + phoneNo.charAt(i);

				}
				if (phoneReceivers.length() != 14) {
					phoneReceivers = "002" + phoneReceivers;
				}
				MultiAutoCompleteTextView contact = (MultiAutoCompleteTextView) findViewById(R.id.AddContact);
				contact.setText(phoneReceivers);
			}
		});

		window.show();
	}

	/**
	 * Validates all the views
	 * 
	 * @author loai,
	 */
	public void validateAllInputs(View v) {

		/**
		 * @author Emy Contacts validation: make sure that the number entered by
		 *         the user is a valid mobile number by extracting the number
		 *         from the AutoComplete field and compare it with the Pattern
		 *         specified in the method! A Hashtable is used to avoid sending
		 *         duplicate numbers to the server.
		 */
		// if it is self alarm, no need for contact check
		if (!(this instanceof CreateAlarm)) {

			Hashtable<String, String> eliminate_duplicates = new Hashtable<String, String>();
			TextView contact_err = (TextView) findViewById(R.id.contact_error);

			// make sure the phone number is valid else User has to re-enter the
			// phone number data!
			final MultiAutoCompleteTextView mobileField = (MultiAutoCompleteTextView) findViewById(R.id.AddContact);
			String displayedText = mobileField.getText().toString();

			Pattern phonePattern = Pattern
					.compile("^[0][0][2][0][1][0-9]{9,9}$");

			phoneReceivers = "";
			names = "";
			contact_err.setText("");
			boolean first = true;

			String[] split_on_comma = displayedText.split(",");
			for (int i = 0; i < split_on_comma.length; i++) {
				String[] split_on_br = split_on_comma[i].split("<");
				Log.d(TAG, "length:" + split_on_br.length);
				if (split_on_br.length == 1) {
					names += ", ";
					Log.d(TAG, "Number without a name");
				}
				String temp = "";
				for (int j = 0; j < split_on_br.length; j++) {
					temp = split_on_br[j];
					split_on_br[j] = formulatePhone(split_on_br[j]);
					try {
						Double.parseDouble(split_on_br[j]);
						Log.d(TAG, "Parsed!");
						if (first) {
							eliminate_duplicates.put(split_on_br[j],
									split_on_br[j]);
							phoneReceivers = split_on_br[j];
							first = false;
						} else {
							if (!eliminate_duplicates.contains(split_on_br[j])) {
								eliminate_duplicates.put(split_on_br[j],
										split_on_br[j]);
								phoneReceivers += ";" + split_on_br[j];
							}
						}
						if (!phonePattern.matcher(split_on_br[j]).matches()) {
							contact_err
									.setText(getString(R.string.invalid_number)
											+ ": " + split_on_br[j]);
							return;
						}
					} catch (Exception e) {
						names += "," + temp;
						Log.d(TAG, "Not parsed!");
					}
				}
			}
			if (phoneReceivers == "") {
				contact_err.setText(getString(R.string.insert_num));
				return;
			}
			Log.d(TAG, "numbers:" + phoneReceivers);
			names = names.substring(1, names.length());
			Log.d(TAG, "names:" + names);

			String[] phones = phoneReceivers.split(";");
			try {
				for (int i = 0; i < phones.length; i++) {
					JSONObject js = new JSONObject();
					js.put("phoneReceiver", phones[i]);
					phoneReceiversJson.put(js);
				}
				Log.e("JSON", phoneReceiversJson.toString());
			} catch (Exception e) {
				Log.e("Exception", e.getMessage());
			}
		}
		TextView date_err = (TextView) v.findViewById(R.id.date_error);

		if (start.compareTo(end) > 0) {
			date_err.setText(getString(R.string.erron_in_date));
			return;
		}
		// phoneReceivers = phoneReceivers.replace(",", ";");
		boolean ok = true;
		for (int i = 0; i < notificationsList.getChildCount() && ok; i++)
			ok = validateInput(notificationsList.getChildAt(i));
		if (!ok)
			return;
		Log.d(TAG, "All inputs are valid!");

		final CheckBox checkBox = (CheckBox) findViewById(R.id.favortite_contacts);
		if (checkBox.isChecked()) {
			saveContacts(names, phoneReceivers);
		}
		insertDB(currentUserId, phoneReceivers, place, type, when);
	}

	 /**
     * Retrieves the geopoint (lat,long) corresponding to the user's entered address
     * @param addr
     * @return
     * @author Dalia
     */
    public GeoPoint getGeoPoint(String addr){
            GeoPoint result = new GeoPoint(-91,-181);
            
            Geocoder geoCoder = new Geocoder(getBaseContext(),Locale.getDefault());
             try {
                    List<Address> addresses = geoCoder.getFromLocationName(addr, 1);
                    if (addresses.size() > 0) 
        {
            //get all address lines
            for (int i=0; i<addresses.get(0).getMaxAddressLineIndex(); 
                 i++)
               result = new GeoPoint((int)addresses.get(0).getLatitude()*1000000,
               (int)addresses.get(0).getLongitude()*1000000);
        }
            } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Log.e(TAG, "Address to GeoPoint Problem");
            }
            
            return result;
    }
	/***
	 * @author Emy validate the input of the address and amount of
	 *         minutes/metres and insert an error message in case of an invalid
	 *         input such as a not entered field
	 * @author Loai validation of the start and end date
	 **/
	public boolean validateInput(View v) {

		TextView dest_err = (TextView) v.findViewById(R.id.address_error);
		TextView yalla_err = (TextView) v.findViewById(R.id.time_error);

		 // make sure the address is inserted
        // for user will only choose from map, cannot enter explicitly
        final EditText address = (EditText) v.findViewById(R.id.address);
        String a = address.getText().toString();
        if (a.length() == 0) {
                Toast.makeText(this, R.string.invalid_dest, Toast.LENGTH_SHORT)
                                .show();
                dest_err.setText(R.string.invalid_dest);
                return false;
        } else{
                dest_err.setText("");
                String[] loc = a.split(",");
                if(loc.length==2){
                        double lat = Double.parseDouble(loc[0]);
                        double lon = Double.parseDouble(loc[1]);
                        if(lat>=-90 && lat<=90 && lon>=-180 && lon<=180){
                                adapter.getSelected().setLocation(lat, lon);
                                // set place, temp usage only
                                if (adapter.itemPos == 0)
                                        place = adapter.getPlace(0);
                                adapter.notifyDataSetChanged();
                        }
                        else{
                                Toast.makeText(this, R.string.invalid_dest, Toast.LENGTH_SHORT)
                                .show();
                                dest_err.setText(R.string.invalid_dest);
                                return false;
                        }
                        
                }
                else{
                        GeoPoint p = getGeoPoint(a);
                        if(p.getLatitudeE6()==-91 && p.getLongitudeE6()==-181){
                                Toast.makeText(this, R.string.invalid_dest, Toast.LENGTH_SHORT)
                                .show();
                                dest_err.setText(R.string.invalid_dest);
                                return false;
                        }
                        else{
                                adapter.getSelected().setLocation(p.getLatitudeE6()/1000000.0
                                                , p.getLongitudeE6()/1000000.0);
                                // set place, temp usage only
                                if (adapter.itemPos == 0)
                                        place = adapter.getPlace(0);
                                adapter.notifyDataSetChanged();
                        }
                }
        }
		// make sure that the user entered a number in the edit text for the
		// when section
		// not complete
		final EditText wann = (EditText) v.findViewById(R.id.amount);
		int index = (Integer) v.getTag(R.integer.INDEX_TAG);
		boolean type = adapter.get(index).type;
		if (wann.getText().length() == 0) {
			if (!type) {
				Toast.makeText(this, R.string.invalid_time, Toast.LENGTH_SHORT)
						.show();
				yalla_err.setText(R.string.invalid_time);
			} else {
				Toast.makeText(this, R.string.invalid_dist, Toast.LENGTH_SHORT)
						.show();
				yalla_err.setText(R.string.invalid_dist);
			}
			return false;
		}

		return true;
	}

	/**
	 * Saves the contacts into the local favorites database
	 * 
	 * @author Aya Kamel
	 * @param names
	 *            The names of the contacts to be added
	 * @param phoneReceivers
	 *            The phone numbers of the contacts to be added
	 */
	public void saveContacts(String names, String phoneReceivers) {
		DbAdapter ldb = new DbAdapter(this);
		if (!ldb.isOpened)
			ldb.open();
		String[] names_list = names.split(",");
		String[] phones_list = phoneReceivers.split(";");
		for (int i = 0; i < phones_list.length; i++) {
			String name = names_list[i];
			if(name.equals(" "))
			{
				name = "Unnamed";
			}
			else
			{
				name = name.replace(" ", "");
			}
			ldb.addContact(name, phones_list[i]);
		}
		ldb.close();

	}

	/***
	 * @author Dalia
	 * 
	 *         Method for database insertion Needs to be overridden in child
	 *         classes, mainly to change the server path
	 ** */
	protected void insertDB(long userId, String phone, String place,
			boolean type, int when) {

	}

	class Notification {
		/**
		 * @author loai
		 */
		/**
		 * Place to be notified at
		 */
		public double latitude = -1, longitude = -1;
		/**
		 * Type of measurement of length, whether it is time or distance
		 */
		public boolean type = false;

		/**
		 * Distance from target, in minutes or meters
		 */
		public int when;

		public Notification() {
		}

		public void setLocation(double latitude, double longitude) {
			this.latitude = latitude;
			this.longitude = longitude;
		}
	}

	class NotificationAdapter {
		ArrayList<Notification> notifications;
		int itemPos;

		public NotificationAdapter(LinearLayout layout) {
			notifications = new ArrayList<Notification>();
			addNotification();
		}

		public String getPlace(int index) {
			View v = notificationsList.getChildAt(index);
			EditText address = (EditText) v.findViewById(R.id.address);
			return address.getText().toString();
		}

		public int getWhen(int index) {
			View v = notificationsList.getChildAt(index);
			EditText when = (EditText) v.findViewById(R.id.amount);
			return Integer.parseInt(when.getText().toString());
		}

		public Notification get(int index) {
			return notifications.get(index);
		}

		public Notification getSelected() {
			return get(itemPos);
		}

		public void addNotification() {
			addNotification(notificationsList.getChildCount());
		}

		public void addNotification(int index) {
			Notification notification = new Notification();
			notifications.add(index, notification);
			LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			View v = vi.inflate(R.layout.notification_row, null);
			notificationsList.addView(v, index);
			if (index != 0) {
				refreshView(index);
				// set the new view with default values
				View previous = notificationsList.getChildAt(index - 1);
				EditText address = (EditText) v.findViewById(R.id.address);
				EditText addressPrev = (EditText) previous
						.findViewById(R.id.address);
				address.setText(addressPrev.getText());

				EditText when = (EditText) v.findViewById(R.id.amount);
				EditText whenPrev = (EditText) previous
						.findViewById(R.id.amount);
				when.setText(whenPrev.getText());

				Spinner distanceTime = (Spinner) v
						.findViewById(R.id.spinner_when);
				Spinner distanceTimePrev = (Spinner) previous
						.findViewById(R.id.spinner_when);
				distanceTime.setSelection(distanceTimePrev
						.getSelectedItemPosition());
				notification.type = notifications.get(index - 1).type;
			}
			notifyDataSetChanged();
		}

		public void removeNotification(int index) {
			notifications.remove(index);
			notificationsList.removeViewAt(index);
			notifyDataSetChanged();
		}

		public int size() {
			return notifications.size();
		}

		public void notifyDataSetChanged() {
			assert (notifications.size() == notificationsList.getChildCount());
			for (int i = 0; i < size(); i++)
				refreshView(i);
			notificationsList.refreshDrawableState();
			Log.e("Linearview size", "" + notificationsList.getChildCount());
		}

		public void refreshView(int index) {
			Log.e("Refreshing view", index + "");
			View v = notificationsList.getChildAt(index);
			v.setTag(R.integer.INDEX_TAG, index);
			Log.e("View", v.getTag().toString());

			Spinner distance_time_spinner = (Spinner) v
					.findViewById(R.id.spinner_when);
			// first time
			if (distance_time_spinner.getAdapter() == null) {
				ArrayAdapter<CharSequence> distance_time_adapter = ArrayAdapter
						.createFromResource(CreateNotification.this,
								R.array.distance_time_array,
								android.R.layout.simple_spinner_item);
				distance_time_adapter
						.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
				distance_time_spinner.setAdapter(distance_time_adapter);
			}

			distance_time_spinner.setTag(R.integer.INDEX_TAG, index);
			distance_time_spinner
					.setOnItemSelectedListener(distanceTimeListener);

			ImageView addNotification = (ImageView) v
					.findViewById(R.id.addNotificationButton);
			addNotification.setTag(R.integer.INDEX_TAG, index);
			ImageView removeNotification = (ImageView) v
					.findViewById(R.id.removeNotificationButton);
			removeNotification.setTag(R.integer.INDEX_TAG, index);
			addNotification.setOnClickListener(addRemoveImageClickListener);
			removeNotification.setOnClickListener(addRemoveImageClickListener);
			// There is only one form, no remove option
			if (notificationsList.getChildCount() == 1) {
				removeNotification.setVisibility(android.view.View.GONE);
				removeNotification.setEnabled(false);
			} else {
				removeNotification.setVisibility(android.view.View.VISIBLE);
				removeNotification.setEnabled(true);
			}
			ImageView mapButton = (ImageView) v.findViewById(R.id.mapButton);
			mapButton.setTag(R.integer.INDEX_TAG, index);
			Notification notification = get(index);

			EditText address = (EditText) v.findViewById(R.id.address);
			double latitude = notification.latitude;
			double longitude = notification.longitude;
			// Location is set
			if (latitude != -1 && longitude != -1)
				address.setText(latitude + "," + longitude);

		}
	}
}
